package com.salon.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.salon.common.exception.CustomException;
import com.salon.common.http.response.PageResult;
import com.salon.common.utils.Constant;
import com.salon.common.utils.Query;
import com.salon.modules.sys.entity.SysRoleEntity;
import com.salon.modules.sys.entity.SysUserEntity;
import com.salon.modules.sys.mapper.SysRoleMapper;
import com.salon.modules.sys.service.ISysRoleMenuService;
import com.salon.modules.sys.service.ISysRoleService;
import com.salon.modules.sys.service.ISysUserRoleService;
import com.salon.modules.sys.service.ISysUserService;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 角色
 */
@Service("sysRoleService")
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRoleEntity>
        implements ISysRoleService {

    @Resource
    private ISysRoleMenuService sysRoleMenuService;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ISysUserRoleService sysUserRoleService;

    @Override
    public PageResult<SysRoleEntity> listByPage(Map<String, Object> params) {
        IPage<SysRoleEntity> pageParams = new Query<SysRoleEntity>().getPage(params);
        LambdaQueryWrapper<SysRoleEntity> queryWrapper = new LambdaQueryWrapper<>();
        String roleName = (String) params.get("roleName");
        Long createUserId = (Long) params.get("createUserId");
        queryWrapper.like(StringUtils.isNotBlank(roleName), SysRoleEntity::getRoleName, roleName);
        queryWrapper.eq(Objects.nonNull(createUserId), SysRoleEntity::getCreateUserId, createUserId);
        IPage<SysRoleEntity> page = this.page(pageParams, queryWrapper);
        List<SysRoleEntity> resultList = page.getRecords();
        return new PageResult<>(page.getTotal(), page.getCurrent(), page.getSize(), resultList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRole(SysRoleEntity role) {
        role.setCreateTime(new Date());
        this.save(role);
        // 检查权限是否越权
        checkPermission(role);
        // 保存角色与菜单关系
        sysRoleMenuService.saveOrUpdate(role.getRoleId(), role.getMenuIdList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysRoleEntity role) {
        this.updateById(role);
        // 检查权限是否越权
        checkPermission(role);
        // 更新角色与菜单关系
        sysRoleMenuService.saveOrUpdate(role.getRoleId(), role.getMenuIdList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(Long[] roleIds) {
        // 删除角色
        this.removeByIds(Arrays.asList(roleIds));
        // 删除角色与菜单关联
        sysRoleMenuService.deleteBatch(roleIds);
        // 删除角色与用户关联
        sysUserRoleService.deleteBatch(roleIds);
    }

    @Override
    public List<Long> listRoleIdByUserId(Long createUserId) {
        return baseMapper.listRoleIdByUserId(createUserId);
    }

    /**
     * 检查权限是否越权
     */
    private void checkPermission(SysRoleEntity role) {
        // 如果不是超级管理员，则需要判断角色的权限是否超过自己的权限
        if (role.getCreateUserId() == Constant.SUPER_ADMIN) {
            return;
        }
        // 查询用户所拥有的菜单列表
        List<Long> menuIdList = sysUserService.listMenuIdsByUserId(role.getCreateUserId());
        //判断是否越权
        if (!menuIdList.containsAll(role.getMenuIdList())) {
            throw new CustomException("新增角色的权限，已超出你的权限范围");
        }
    }

    @Override
    public Set<String> getRolePermission(SysUserEntity user) {
        Set<String> roles = new HashSet<>();
        // 管理员拥有所有权限
        if (user.getCreateUserId() == Constant.SUPER_ADMIN) {
            roles.add("admin");
        } else {
            List<SysRoleEntity> perms = baseMapper.listRolePermsByUserId(user.getUserId());
            Set<String> permsSet = new HashSet<>();
            for (SysRoleEntity perm : perms) {
                permsSet.addAll(Arrays.asList(perm.getRoleName().trim().split(",")));
            }
            roles.addAll(permsSet);
        }
        return roles;
    }
}
